/* $Id: NonClientPersonRegisterFacadeImpl.java 
 * Copyright (C) 2011, TRAKHEES
 *  
 * Revision History
 *
 * Date  			Author 		    	Remarks
 * ---------------------------------------------------------------------------------
 *
 */
package ae.pcfc.etks.online.common.facade.provider;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.transaction.annotation.Transactional;

import ae.pcfc.etks.online.common.ConstantsCommon;
import ae.pcfc.etks.online.common.ConstantsCommon.WorkflowDepartment;
import ae.pcfc.etks.online.common.domain.AppMetaData;
import ae.pcfc.etks.online.common.domain.ClientPersonReq;
import ae.pcfc.etks.online.common.domain.ProcStepAthmnt;
import ae.pcfc.etks.online.common.domain.TTscClientCategory;
import ae.pcfc.etks.online.common.domain.TTscClientRoleToDepartmentMap;
import ae.pcfc.etks.online.common.domain.TTscDepartments;
import ae.pcfc.etks.online.common.domain.manager.AppMetaDataDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.AttachmentTypeDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.NonClientCompanyDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.NonClientPersonDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.ProcessDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.SingleClientPersonDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.UtilityDomainObjectManager;
import ae.pcfc.etks.online.common.exception.DuplicateClientEmailException;
import ae.pcfc.etks.online.common.exception.DuplicateClientNameException;
import ae.pcfc.etks.online.common.facade.NonClientPersonRegisterFacade;
import ae.pcfc.etks.online.common.vo.ClientCategoryVO;
import ae.pcfc.etks.online.common.vo.ClientNameVO;
import ae.pcfc.etks.online.common.vo.ClientRoleVO;
import ae.pcfc.etks.online.common.vo.NonClientPersonVO;
import ae.pcfc.etks.online.common.vo.UploadDocumentVO;
import ae.pcfc.etks.online.wf.service.client.NonClientWF;
import ae.pcfc.etks.online.wf.service.client.vo.LaunchIncidentVO;

public class NonClientPersonRegisterFacadeImpl extends BaseFacade implements
		NonClientPersonRegisterFacade {
    	/*
	 * Here we coordinate between the all interacting business domain objects
	 * (BO), transactions are maintained here. use case business validation are
	 * maintained here (that requires DB checks or retrieving data from DB)
	 */
	private NonClientPersonDomainObjectManager nonClientPersonDomainObjectManager;
	private AttachmentTypeDomainObjectManager attachmentTypeDomainObjectManager;
	private AppMetaDataDomainObjectManager appMetaDataDomainObjectManager;
	private ProcessDomainObjectManager processDomainObjectManager;
	private NonClientWF nonClientPersonWF;
	private SingleClientPersonDomainObjectManager singleClientPersonDomainObjectManager;

	private UtilityDomainObjectManager utilityDomainObjectManager;
	private NonClientCompanyDomainObjectManager nonClientCompanyDomainObjectManager;
	
	public NonClientCompanyDomainObjectManager getNonClientCompanyDomainObjectManager() {
	    return nonClientCompanyDomainObjectManager;
	}

	public void setNonClientCompanyDomainObjectManager(
		NonClientCompanyDomainObjectManager nonClientCompanyDomainObjectManager) {
	    this.nonClientCompanyDomainObjectManager = nonClientCompanyDomainObjectManager;
	}

	public NonClientPersonDomainObjectManager getNonClientPersonDomainObjectManager() {
	    return nonClientPersonDomainObjectManager;
	}
	/**
	 * getUtilityDomainObjectManager
	 * 
	 * @return
	 * UtilityDomainObjectManager
	 */
	public UtilityDomainObjectManager getUtilityDomainObjectManager() {
		return utilityDomainObjectManager;
	}

	/**
	 * setUtilityDomainObjectManager
	 * 
	 * @param utilityDomainObjectManager
	 * void
	 */
	public void setUtilityDomainObjectManager(
			UtilityDomainObjectManager utilityDomainObjectManager) {
		this.utilityDomainObjectManager = utilityDomainObjectManager;
	}

	/**
	 * setNonClientPersonWF
	 * 
	 * @param nonClientPersonWF
	 * void
	 */
	public void setNonClientPersonWF(NonClientWF nonClientPersonWF) {
		this.nonClientPersonWF = nonClientPersonWF;
	}

	/**
	 * setNonClientPersonDomainObjectManager
	 * 
	 * @param nonClientPersonDomainObjectManager
	 * void
	 */
	public void setNonClientPersonDomainObjectManager(
			NonClientPersonDomainObjectManager nonClientPersonDomainObjectManager) {
		this.nonClientPersonDomainObjectManager = nonClientPersonDomainObjectManager;
	}

	/**
	 * setAppMetaDataDomainObjectManager
	 * 
	 * @param appMetaDataDomainObjectManager
	 * void
	 */
	public void setAppMetaDataDomainObjectManager(
			AppMetaDataDomainObjectManager appMetaDataDomainObjectManager) {
		this.appMetaDataDomainObjectManager = appMetaDataDomainObjectManager;
	}

	/**
	 * setProcessDomainObjectManager
	 * 
	 * @param processDomainObjectManager
	 * void
	 */
	public void setProcessDomainObjectManager(
			ProcessDomainObjectManager processDomainObjectManager) {
		this.processDomainObjectManager = processDomainObjectManager;
	}

	/**
	 * setAttachmentTypeDomainObjectManager
	 * 
	 * @param attachmentTypeDomainObjectManager
	 * void
	 */
	public void setAttachmentTypeDomainObjectManager(
			AttachmentTypeDomainObjectManager attachmentTypeDomainObjectManager) {
		this.attachmentTypeDomainObjectManager = attachmentTypeDomainObjectManager;
	}

	/**
	 * setSingleClientPersonDomainObjectManager
	 * 
	 * @param singleClientPersonDomainObjectManager
	 * void
	 */
	public void setSingleClientPersonDomainObjectManager(
			SingleClientPersonDomainObjectManager singleClientPersonDomainObjectManager) {
		this.singleClientPersonDomainObjectManager = singleClientPersonDomainObjectManager;
	}

	/**
	 * registerNonClientPerson
	 * 
	 * @see ae.pcfc.etks.online.common.facade.NonClientPersonRegisterFacade#registerNonClientPerson(ae.pcfc.etks.online.common.vo.NonClientPersonVO)
	 * 
	 */
	@Transactional
	public String registerNonClientPerson(NonClientPersonVO nonClientPersonVO) {
		/*if (validateNonClientPersonReq(nonClientPersonVO)) {*/
			AppMetaData appMetaData = new AppMetaData();

			ae.pcfc.etks.online.common.domain.Process process = processDomainObjectManager
					.getProcessByProcessAndStepCode(
							nonClientPersonVO.getProcessCode().getProcessCode(),
							nonClientPersonVO.getStrProcessStep());
			appMetaData.setProcess(process);

			getMapper().map(nonClientPersonVO, appMetaData);

			/***
			 * Mapper is not used because i have to set the attachment types
			 * which are in the nested entity
			 ***/
			Set<ProcStepAthmnt> procStepAtmnt = new HashSet<ProcStepAthmnt>();
			List<UploadDocumentVO> documentVOs = nonClientPersonVO
					.getArrDocumentVOs();
			ProcStepAthmnt athmnt;

			for (UploadDocumentVO documentVO : documentVOs) {
				athmnt = new ProcStepAthmnt();
				athmnt.setAppMetaData(appMetaData);
				// Can we do this?
				athmnt.setProcessStep(process.getProcessSteps().iterator()
						.next());
				athmnt.setAttachmentPath(documentVO.getURL());
				athmnt.setAttachmentType(attachmentTypeDomainObjectManager
						.getAttachmentTypeByAttachmentCode(documentVO
								.getStrUploadDocumentType()));
				procStepAtmnt.add(athmnt);
			}

			if (procStepAtmnt.size() > 0)
				appMetaData.setProcStepAthmnts(procStepAtmnt);
	
			appMetaDataDomainObjectManager.add(appMetaData);

			// Storing the Client Person Details
			ClientPersonReq clientPersonReq = new ClientPersonReq();
			getMapper().map(nonClientPersonVO, clientPersonReq);

			clientPersonReq.setApplicationId(appMetaData.getApplicationId());
			nonClientPersonDomainObjectManager.add(clientPersonReq);

			return appMetaData.getClientRefNo();
		/*} else
			return null;*/
	}

	/**
	 * validateNonClientPersonReq
	 * 
	 * @param nonClientPersonVO
	 * @return
	 * boolean
	 */
	@Transactional(readOnly = true)
	public boolean validateNonClientPersonReq(
			NonClientPersonVO nonClientPersonVO) {
		ClientNameVO clientNameVO = new ClientNameVO();
		clientNameVO.setStrNameEng(nonClientPersonVO
				.getStrNonClientPersonNameENG());
		if (this.singleClientPersonDomainObjectManager
				.validateClientName(clientNameVO)) {

			clientNameVO.setStrNameEng(null);
			clientNameVO.setStrNameArb(nonClientPersonVO
					.getStrNonClientPersonNameARB());

			if (this.singleClientPersonDomainObjectManager
					.validateClientName(clientNameVO)) {
				if (this.singleClientPersonDomainObjectManager
						.findTrakheesIdAndPinByEmail(nonClientPersonVO
								.getStrEmailAddress()) == null) {
					if (this.nonClientPersonDomainObjectManager
							.validateByPropertyName("cpNamEng",
									nonClientPersonVO
											.getStrNonClientPersonNameENG())) {
						if (this.nonClientPersonDomainObjectManager
								.validateByPropertyName("cpNameArb",
										nonClientPersonVO
												.getStrNonClientPersonNameARB())) {
							if (this.nonClientPersonDomainObjectManager.validateByPropertyName("cpEmail",nonClientPersonVO.getStrEmailAddress())
							&&this.nonClientCompanyDomainObjectManager.validateByPropertyName("ccEmail",nonClientPersonVO.getStrEmailAddress())) {

							} else {
								throw new DuplicateClientEmailException(
										nonClientPersonVO.getStrEmailAddress());
							}
						} else {
							throw new DuplicateClientNameException(
									nonClientPersonVO
											.getStrNonClientPersonNameARB());
						}
					} else {
						throw new DuplicateClientNameException(
								nonClientPersonVO
										.getStrNonClientPersonNameENG());
					}
				} else {
					throw new DuplicateClientEmailException(
							nonClientPersonVO.getStrEmailAddress());
				}
			} else {
				throw new DuplicateClientNameException(
						nonClientPersonVO.getStrNonClientPersonNameARB());
			}
		} else {
			throw new DuplicateClientNameException(
					nonClientPersonVO.getStrNonClientPersonNameENG());
		}

		return true;

		/*
		 * ClientNameVO clientNameVO = new ClientNameVO();
		 * clientNameVO.setStrNameEng
		 * (nonClientPersonVO.getStrNonClientPersonNameENG());
		 * 
		 * if (this.singleClientPersonDomainObjectManager.validateClientName(
		 * clientNameVO)) {
		 * 
		 * if
		 * (this.nonClientPersonDomainObjectManager.findByPropertyName("cpNamEng"
		 * , nonClientPersonVO.getStrNonClientPersonNameENG()) == null) {
		 * 
		 * clientNameVO.setStrNameEng(null);
		 * clientNameVO.setStrNameArb(nonClientPersonVO
		 * .getStrNonClientPersonNameARB());
		 * 
		 * if (this.singleClientPersonDomainObjectManager.validateClientName(
		 * clientNameVO)) {
		 * 
		 * if
		 * (this.nonClientPersonDomainObjectManager.findByPropertyName("cpNameArb"
		 * , nonClientPersonVO.getStrNonClientPersonNameARB()) == null) {
		 * 
		 * if
		 * (this.nonClientPersonDomainObjectManager.findByPropertyName("cpEmail"
		 * , nonClientPersonVO.getStrEmailAddress()) == null) {
		 * 
		 * if
		 * (this.singleClientPersonDomainObjectManager.findTrakheesIdAndPinByEmail
		 * (nonClientPersonVO .getStrEmailAddress()) == null) {
		 * 
		 * if (this.nonClientCompanyDomainObjectManager.
		 * getNonClientCompanyByPropertyName("ccEmail",
		 * nonClientPersonVO.getStrEmailAddress()) == null) {
		 * 
		 * } else { throw new
		 * DuplicateClientEmailException(nonClientPersonVO.getStrEmailAddress
		 * ()); }
		 * 
		 * } else { throw new
		 * DuplicateClientEmailException(nonClientPersonVO.getStrEmailAddress
		 * ()); }
		 * 
		 * } else { throw new
		 * DuplicateClientEmailException(nonClientPersonVO.getStrEmailAddress
		 * ()); }
		 * 
		 * } else { throw new DuplicateClientNameException(nonClientPersonVO.
		 * getStrNonClientPersonNameARB()); }
		 * 
		 * } else { throw new DuplicateClientNameException(nonClientPersonVO.
		 * getStrNonClientPersonNameARB()); }
		 * 
		 * } else { throw new DuplicateClientNameException(nonClientPersonVO.
		 * getStrNonClientPersonNameENG()); }
		 * 
		 * } else { throw new DuplicateClientNameException(nonClientPersonVO.
		 * getStrNonClientPersonNameENG()); }
		 * 
		 * return true;
		 */}

	/**
	 * getClientCategory
	 * 
	 * @see ae.pcfc.etks.online.common.facade.NonClientPersonRegisterFacade#getClientCategory(java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public List<ClientCategoryVO> getClientCategory(String clientType) {

		List<TTscClientCategory> clientCategories = this.singleClientPersonDomainObjectManager
				.getClientCategory(clientType);

		List<ClientCategoryVO> clientCategoryVos = new ArrayList<ClientCategoryVO>(
				0);

		for (TTscClientCategory clientCategory : clientCategories) {

			ClientCategoryVO clientCategoryVO = new ClientCategoryVO();

			getMapper().map(clientCategory, clientCategoryVO);

			clientCategoryVos.add(clientCategoryVO);

		}

		return clientCategoryVos.size() > 0 ? clientCategoryVos : null;
	}
	
	/**
	 * updateWorkflowIncidentVO
	 * Method to set the departments which should act on the workflow request in the Workflow request Object(LaunchIncidentVO)
	 * @param launchIncidVO
	 * @param list
	 * void
	 */
	@Transactional(readOnly = true)
	public void updateWorkflowIncidentVO(LaunchIncidentVO launchIncidVO, List<ClientRoleVO> list){
		if(launchIncidVO != null && list != null){
			List<String> strClientRoles = new ArrayList<String>();
			for(ClientRoleVO roleId : list){
				strClientRoles.add(roleId.getStrCrId());
			}
			List<TTscClientRoleToDepartmentMap> departments = this.utilityDomainObjectManager.getDepartmentsByRoleIds(strClientRoles);
			
			if( departments == null ){
				departments = new ArrayList<TTscClientRoleToDepartmentMap>();
			}
			
			List<String> strDepartments = new ArrayList<String>();
			List<WorkflowDepartment> wfDepartments = new ArrayList<WorkflowDepartment>();
			for(TTscClientRoleToDepartmentMap deptMap : departments){
				TTscDepartments dept = deptMap.getDepartment();
				strDepartments.add(dept.getDeptCode().toUpperCase());
				wfDepartments.add(WorkflowDepartment.getWorkflowDepartmentfromString(dept.getDeptCode()));
			}
			launchIncidVO.setgApprovalFIN(ConstantsCommon.SET_VALUE);
			if(strDepartments.contains(WorkflowDepartment.CED.getCode())){
				launchIncidVO.setgApprovalCED(ConstantsCommon.SET_VALUE);
			}else{
				launchIncidVO.setgApprovalCED(ConstantsCommon.UNSET_VALUE);
			}
			if(strDepartments.contains(WorkflowDepartment.CLD.getCode())){
				launchIncidVO.setgApprovalCLD(ConstantsCommon.SET_VALUE);
			}else{
				launchIncidVO.setgApprovalCLD(ConstantsCommon.UNSET_VALUE);
			}
			if(strDepartments.contains(WorkflowDepartment.EHS.getCode())){
				launchIncidVO.setgApprovalEHS(ConstantsCommon.SET_VALUE);
			}else{
				launchIncidVO.setgApprovalEHS(ConstantsCommon.UNSET_VALUE);
			}
		}
	}

}